#!/usr/bin/python

"""
__version__ = "$Revision: 1.18 $"
__date__ = "$Date: 2005/12/13 11:13:23 $"
"""

from PythonCard import dialog, log, model
import wx
import fpoputil

class Message(model.Background):

    def on_initialize(self, event):
        self.parent = self.GetParent()
        self.sent = 0
        self.modified = 0
        # openBackground is an event, so it actually might
        # occur after displayMessage is called below
        if not hasattr(self, 'msg'):
            self.msg = None
        self.initSizers()

    def initSizers(self):
        comp = self.components
        
        sizer1 = wx.BoxSizer(wx.VERTICAL)
        sizer2 = wx.FlexGridSizer(3, 2, 3, 10)
        sizer2.AddGrowableCol(1)
        
        stcSizerAttrs = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL         
        fldSizerAttrs = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND
        vertFlags = wx.LEFT | wx.TOP | wx.ALIGN_LEFT
        chkSizerAttrs = wx.RIGHT | wx.ALIGN_CENTER_VERTICAL

        sizer2.Add(comp.stcTo, flag=stcSizerAttrs)
        sizer2.Add(comp.fldTo, flag=fldSizerAttrs)
        sizer2.Add(comp.stcCc, flag=stcSizerAttrs)
        sizer2.Add(comp.fldCc, flag=fldSizerAttrs)
        sizer2.Add(comp.stcSubject, flag=stcSizerAttrs)
        sizer2.Add(comp.fldSubject, flag=fldSizerAttrs)

        sizer1.Add(sizer2, 0, wx.EXPAND) #vertFlags)
        sizer1.Add((5, 5), 0)  # spacer
        sizer1.Add(comp.fldBody, 1, wx.EXPAND)
        
        sizer1.Fit(self)
        sizer1.SetSizeHints(self)
        self.panel.SetSizer(sizer1)
        self.panel.SetAutoLayout(1)
        self.panel.Layout()

    def displayMessage(self, msg=None):
        self.msg = msg
        comp = self.components
        #comp.fldSender.text = fpoputil.joinList(msg.get_all('sender'))
        #comp.fldFrom.text = fpoputil.joinList(msg.get_all('from'))
        comp.fldTo.text = fpoputil.joinList(msg.get_all('to'))
        comp.fldCc.text = fpoputil.joinList(msg.get_all('cc'))
        comp.fldSubject.text = msg.get('subject', '(None)')
        #comp.fldDate.text = fpoputil.dateString(msg.get('date'))

        text = fpoputil.getBody(msg)
        comp.fldBody.text = text

    def on_menuFileClose_select(self, event):
        self.close()

    # once SMTP is figured out, this
    # can be broken up an the actual sending
    # can be in the fpoputil.py module rather
    # than mixed in with the GUI code
    def on_send_command(self, event):
        comp = self.components
        if self.msg.has_key('references'):
            references = self.msg['references']
        else:
            references = None
        if self.msg.has_key('in-reply-to'):
            inReplyTo = self.msg['in-reply-to']
        else:
            inReplyTo = None

        fromName = self.parent.fromName
        fromAttribution = self.parent.fromAttribution
        fromAddress = self.parent.fromAddress
        replyAddress = self.parent.replyAddress
        username = self.parent.POPuser
        # should have a separate entry for SMTP server
        # username and password?
        servername = self.parent.POPserver
        password = self.parent.POPpwd
        to = comp.fldTo.text
        cc = comp.fldCc.text
        subject = comp.fldSubject.text
        body = comp.fldBody.text

        print "sending via SMTP..."
        # what checks should be done prior to sending?
        # if send succeeds, then close the window
        # until we support mailboxes, sent messages can't be saved
        # unless we're going to just save them as text files on disk
        # in a special sub-folder
        import smtplib
        import sys
        import string
        from email import Encoders, Utils
        from email.MIMEText import MIMEText

        #msg = MIMEText(body, _encoder=Encoders.encode_quopri)
        msg = MIMEText(body)

        # how do we handle a list of addresses
        # for to or cc?
        
        # turn to and cc into valid lists
        # this is adapated from Mark Lutz's PyMailGui
        # and might be wrong for the email module
        if cc != '':
            Ccs = cc.split(';') or []
        else:
            Ccs = []
        print "Ccs", Ccs
        Tos = to.split(';') + Ccs
        Tos = map(string.strip, Tos)
        print "Tos", Tos
        
        # me == the sender's email address
        # you == the recipient's email address
        msg['Date'] = Utils.formatdate(localtime=1)
        msg['Subject'] = subject
        # I'm not sure we need to do Reply-to
        #if replyAddress != '':
        #    if fromName != '':
        #        replyAddress = """"%s" <%s>""" % (fromName, replyAddress)
        #    msg['Reply-to'] = replyAddress

        messageId = Utils.make_msgid()
        msg['Message-ID'] = messageId
        
        if references is not None:
            msg['References'] = inReplyTo

        if inReplyTo is not None:
            msg['In-Reply-To'] = inReplyTo
            
        if fromAttribution != '':
            msg['X-Attribution'] = fromAttribution
            
        if fromName != '':
            fromAddress = """"%s" <%s>""" % (fromName, fromAddress)
        msg['From'] = fromAddress
        # should these be in a list format or just strings?
        msg['To'] = to
        if cc != '':
            msg['Cc'] = cc
        msg['X-Mailer'] = 'fpop Version 0.1 (PythonCard)\n'
        # need to create a date field in rfc822 format

        errInfo = ''
        failed  = {}
        try:
            s = smtplib.SMTP(servername)
            s.set_debuglevel(1)
            #s.connect()
            # is logging in harmless?
            #s.login(username, password)
            failed = s.sendmail(fromAddress, Tos, msg.as_string(0))
            #s.close()
            s.quit()
            self.sent = 1
            self.close()
        except:
            exc_type, exc_value = sys.exc_info()[:2]   # thread exc
            excinfo = '\n' + str(exc_type) + '\n' + str(exc_value)
            errInfo = 'Error sending mail\n' + excinfo
            print "errInfo:", errInfo
        else:
            if failed:
                errInfo = 'Failed recipients:\n' + str(failed)
                print "errInfo:", errInfo

    def clearFields(self):
        for field in ['fldTo', 'fldCc', 'fldSubject', 'fldBody']:
            self.components[field].text = ''

    def on_closeField(self, event):
        self.modified = 1
        print "modified"
    
    def on_fldSubject_closeField(self, event):
        # could change the titlebar to show the To or Subject fields
        # to make it easier to identify the window
        self.modified = 1
        self.title = event.target.text

    def on_close(self, event):
        # ask to save here?
        # should really close
        # what about multiple new message windows?
        # remove this window from the list of windows
        if self.modified and not self.sent:
            message = "You haven't sent this message. Close anyway?"
            result = dialog.messageDialog(self, message, 'Unsent Message', \
            wx.ICON_INFORMATION | wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL)
            if result.accepted:
                returned = result.returnedString
                if returned == 'Yes':
                    del self.parent.messageWindows[self.GetId()]
                    event.skip()
        else:
            del self.parent.messageWindows[self.GetId()]
            event.skip()

